package org.offsync.nio

import java.nio.channels.SelectionKey
import java.nio.channels.Selector
import java.nio.channels.spi.SelectorProvider
import collection.JavaConversions._
import scala.collection.{mutable => mutable}
import org.offsync.rich._
import org.offsync.util.Disposable
import org.offsync.util.DisposableBase
import java.util.concurrent.atomic.AtomicInteger
import org.offsync.util.Disposer
import java.nio.channels.ClosedSelectorException

class NioOpSelector(
    disposer: Disposer,
    val op: Int) extends DisposableBase {
  val selector = SelectorProvider.provider().openSelector()
  
  val thread = new Thread() {
    override def run() {
      try {
        while (isLive) {
          selector.selectedKeys.iterator.consume { key =>
            assert(key.readyOps == SelectionKey.OP_CONNECT);
            key.attachment.asInstanceOf[Unit => Unit]()
          }
        }
      } catch {
        case e: ClosedSelectorException =>
      } finally {
        disposer.dispose()
      }
    }
  }
  
  def start() = thread.start()

  def isOpen(): Boolean = selector.isOpen()
  
  def provider(): SelectorProvider = selector.provider()
  
  def keys(): mutable.Set[SelectionKey] = selector.keys()
  
  def selectedKeys(): mutable.Set[SelectionKey] = selector.selectedKeys()
  
  def selectNow(): Int = selector.selectNow()
  
  def select(timeout: Long): Int = selector.select(timeout)
  
  def select(): Int = selector.select()
  
  def wakeup(): Selector = selector.wakeup()
  
  protected override def onDispose(): Unit = {
    try selector.close() catch { case e => }
    
    super.onDispose()
  }
}
